package com.mlh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mlh.entity.Comment;
import com.mlh.enums.AppHttpCodeEnum;
import com.mlh.exception.SystemException;
import com.mlh.mapper.CommentMapper;
import com.mlh.service.CommentService;
import com.mlh.service.UserService;
import com.mlh.util.BeanCopyUtil;
import com.mlh.util.ResponseResult;
import com.mlh.vo.CommentVo;
import com.mlh.vo.PageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 评论表(Comment)表服务实现类
 *
 * @author makejava
 * @since 2024-03-15 20:52:36
 */
@Service("commentService")
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    private UserService userService;

    //获取文章评论列表
    @Override
    public ResponseResult commentList(Long articleId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper();
        // 根据articleId获取评论
        queryWrapper.eq(Comment::getArticleId, articleId);
        // 获取根评论
        queryWrapper.eq(Comment::getRootId, -1);
        Page<Comment> page = new Page<>();
        page(page, queryWrapper);
        // 获取到根评论列表
        List<Comment> commentList = page.getRecords();
        // 要通过vo处理好 要返回给前端的Comment对象的所需格式
        // Vo中属性有需要我们额外的赋值的，这里通过completeCommentVoList()方法来赋值
        List<CommentVo> commentVos = completeCommentVoList(commentList);
        // 查询所有根评论对应的子评论集合，并且赋值给对应的属性
        for (CommentVo commentVo : commentVos) {
            // 获取所有根评论的子评论并赋值
            List<CommentVo> children = getChildrem(commentVo.getId());
            commentVo.setChildren(children);
        }
        PageVo<CommentVo> commentVoPageVo = new PageVo<>(commentVos, page.getTotal());
        // 利用PageVo将数据封装好返回给前端
        return ResponseResult.okResult(commentVoPageVo);
    }

    //补全CommentVo的UserName和ToCommentUserName属性
    private List<CommentVo> completeCommentVoList(List<Comment> list) {
        List<CommentVo> commentVos = BeanCopyUtil.copyBeanList(list, CommentVo.class);
        for (CommentVo commentVo : commentVos) {
            // 设置创建该评论的用户名
            commentVo.setUserName(userService.getById(commentVo.getCreateBy()).getNickName());
            if (commentVo.getToCommentUserId() != -1) {// toCommentUserId=-1 代表该评论不是回复别人的，是没有评论回复的用户名的
                // 设置该评论回复的用户名
                commentVo.setToCommentUserName(userService.getById(commentVo.getToCommentUserId()).getNickName());
            }
        }
        return commentVos;
    }

    //获取根评论的所有子评论
    private List<CommentVo> getChildrem(Long rootId) {
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Comment::getRootId, rootId);
        queryWrapper.orderByAsc(Comment::getCreateTime);
        List<Comment> list = list(queryWrapper);
        return completeCommentVoList(list);
    }

    //发表评论
    @Override
    public ResponseResult addCommetn(Comment comment) {
        //这里还可以对评论内容做一些校验  防止敏感信息出现
        if(!StringUtils.hasText(comment.getContent())){//如果发表的内容为空，返回错误信息
            throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL);
        }
        //此时传过来的comment create_by create_time update_by update_time属性都没有赋值
        //我们利用mp来将这些属性赋值  通过注解方式  这种方式需要实现 MetaObjectHandler接口
        // 在handler/MyMetaObjectHandler我们实现了
        save(comment);
        return ResponseResult.okResult();
    }

    //获取友联评论列表（这里代码高度冗余了，应该和获取文章评论列表合并成一个，新增参数来区分文章和友联）
    @Override
    public ResponseResult linkCommentList(Integer pageNum, Integer pageSize) {
        //友联评论和文章评论用的是同一张表，利用type来区分两者
        //查询友联评论和文章评论逻辑上是一样的
        LambdaQueryWrapper<Comment> queryWrapper=new LambdaQueryWrapper();
        //友联类型为 1
        queryWrapper.eq(Comment::getType,1);
        // 获取友联根评论
        queryWrapper.eq(Comment::getRootId,-1);
        Page<Comment>page=new Page<>(pageNum,pageSize);
        page(page, queryWrapper);
        List<Comment> linkList = page.getRecords();
        //补全友联根评论
        List<CommentVo> commentVos = completeCommentVoList(linkList);
        //获取子评论
        for (CommentVo commentVo : commentVos) {
            commentVo.setChildren(getChildrem(commentVo.getId()));
        }
        //和total封装在一起
        PageVo<CommentVo> result = new PageVo<>(commentVos, page.getTotal());
        return ResponseResult.okResult(result);
    }
}
